###
### SuperGarbage VM with Custom Loader
### Implemented in TurboBooster ISA
###



### Loader ###

loader:
    li $a0, 0x200           # Set initial startPC
    li $a1, 0x0             # Set start of accessible memory
    
    # Report the selected app, using out
    li $t1, 0x1             # Set output channel
    li $t2, 0x0             # Select an app
    out $t2, $t1            
    
    infLoop
loader_while:
    # retrieve first 4 words of memory
    # we need to use 0x0 and 0x1 as temp variables for "in" instruction
    ldinst $zero, $zero     # $op = mem[0x0], $srcA = mem[0x1]

    li $t1, 0x1             # $t1 = 0x1
    
    # Use memory locations 0x0 and 0x1 for "addr" and "data"
    in $zero, $t1           # mem[0x0] = channel[1]
    in $t1, $t1             # mem[0x1] = channel[1]
    
    # $t2 = addr, $t3 = data
    ldr $t2, $zero, $zero   # $t2 = mem[0x0]
    ldr $t3, $t1, $zero     # $t3 = mem[0x1]
    
    # place $op and $srca back into memory 0x0 and 0x1
    sw $op, $zero, 0x0      # mem[0x0] = $op
    sw $srca, $zero, 0x1    # mem[0x1] = $srca
    
if:
    bne $t2, 0x3FFFFFFFF, elseIf
    
    add $a0, $t3, $zero     # startPC = data, $a0 = $t3
    j endWhile              # break out of loop
    
elseIf:    
    staj $t3, $t2           # mem[addr] = data, jump back to while
    
endWhile:
    gic $t3                 # get instruction count up to here
    
    jal sg                  # Call SuperGarbage!
    
    gic $t2                 # get instruction count again
    
    sub $t1, $t2, $t3       # diff the two instruction counts
    li $t3, 0x3             
    out $t1, $t3            # channel[3] = SuperGarbage instruction count
    
    halt
    
### End Loader ###
    
##################################################################################
    
### SuperGarbage Implementation ###

sg:

    infLoop                 # while loop
while:
    ldinst $a0, $a1         # Load the instruction, set up variables
    ldr $srca, $srca, $zero
    ldr $srcb, $srcb, $zero
    addi $a0, $a0, 0x4

    swtch                   # One instruction for switch statement

case0:
    sub $t1, $srca, $srcb   # $t1 = mem[srcA] - mem[srcB]
    staj $t1, $dest         # Store word and jump

case1:
    srl $t1, $srca, 0x1     # $t1 = mem[srcA] >> 1
    staj $t1, $dest

case2:
    nor $t1, $srca, $srcb   # $t1 = ~(mem[srcA] | mem[srcB])
    staj $t1, $dest

case3:
    add $t1, $srcb, $zero   # $t1 = mem[srcB]
    ldr $t2, $srca, $zero   # $t2 = mem[mem[srcA]]
    sw $t2, $dest, 0x0      # mem[dest] = $t2
    staj $t1, $srca         # mem[mem[srcA]] = $t1

case4:
    in $dest, $srca         # mem[dest] = channel[mem[srcA]].first
    j while

case5:
    out $srca, $srcb        # channel[mem[srcB]] = mem[srcA]
    j while

case6:
    sw $a0, $dest, 0x0      # mem[dest] = PC
                            ## if(srcA > -1), then branch
    bgt $srca, 0x3FFFFFFFF, case6_endif     
    add $a0, $srcb, $zero   # PC = mem[srcB]

case6_endif:
    j while

case7:
    add $v0, $a0, $zero           #$v0 = PC
    jr $ra
    
### End SuperGarbage ###
